home *** CD-ROM | disk | FTP | other *** search
- (* :Title: Continuous Time Fourier Transform *)
-
- (* :Authors: Brian Evans, Wallace McClure, James McClellan *)
-
- (* :Summary: *)
-
- (* :Context: SignalProcessing`Analog`Fourier` *)
-
- (* :PackageVersion: 2.7 *)
-
- (*
- :Copyright: Copyright 1990-1991 by Brian L. Evans
- Georgia Tech Research Corporation
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is
- hereby granted, provided that the above copyright notice
- appear in all copies and that both that copyright notice and
- this permission notice appear in supporting documentation,
- and that the name of the Georgia Tech Research Corporation,
- Georgia Tech, or Georgia Institute of Technology not be used
- in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission. Georgia
- Tech makes no representations about the suitability of this
- software for any purpose. It is provided "as is" without
- express or implied warranty.
- *)
-
- (*
- :History: start -- February 22, 1990
- made into package -- April 18, 1990
- added Dialogue ability -- October, 1990
- added many more transform pairs -- February, 1991
- incorporated duality so only one set of transform
- pairs, properties, etc., is encoded -- December, 1991
- *)
-
- (* :Keywords: Fourier transform, frequency response *)
-
- (*
- :Source: {Signals and Systems} by A. V. Oppenheim and A. S. Willsky.
- Prentice Hall.
- {The Fourier Transform and Its Applications} by R. Bracewell
- *)
-
- (* :Warning: *)
-
- (* :Mathematica Version: 1.2 or 2.0 *)
-
- (*
- :Limitation: If the function to be transformed does not match either
- a specific Fourier transform or the LaPlace transform, a
- nasty expression is returned.
- *)
-
- (*
- :Discussion: When loaded into Mathematica, this package will allow the
- computation of continuous Fourier and inverse Fourier
- transforms. It turns out that in order to show a user
- each step of transformation process, the transform rules
- needed to be placed in a list of deferred (delayed) rules.
-
- MyFourier[f, t, w, s] computes the one-dimensional Fourier trans-
- form of f using t as the time variable and w as the frequency
- variable.
-
- MyInverseCTFT[f, w, t, s] computes the inverse one-dimensional
- continuous-time Fourier transform using w as the frequency variable
- and t as the time variable.
-
- The Fourier transform formulas used follow Oppenheim & Willsky.
- To convert Bracewell's formulas, which use 2 Pi s x instead of w t
- in the exponential function,
-
- (1) use x = t and s = w / (2 Pi) OR
- (2) use s = w and x = t / (2 Pi) and divide the time
- function by 2 Pi.
-
- Note that in (2), dividing the time function by 2 Pi is equivalent
- to multiplying the frequency response by 2 Pi. Either way places
- the 1/(2 Pi) normalization term in front of the inverse formula.
- *)
-
- (* :Functions: CTFTransform InvCTFTransform *)
-
-
-
- (* B E G I N P A C K A G E *)
-
- BeginPackage[ "SignalProcessing`Analog`Fourier`",
- "SignalProcessing`Analog`LaPlace`",
- "SignalProcessing`Analog`InvLaPlace`",
- "SignalProcessing`Analog`LSupport`",
- "SignalProcessing`Digital`DSupport`",
- "SignalProcessing`Support`TransSupport`",
- "SignalProcessing`Support`ROC`",
- "SignalProcessing`Support`SigProc`",
- "SignalProcessing`Support`SupCode`" ]
-
-
- If [ TrueQ[ $VersionNumber >= 2.0 ],
- Off[ General::spell ];
- Off[ General::spell1 ] ];
-
-
- (* U S A G E I N F O R M A T I O N *)
-
- CTFTData::usage =
- "CTFTData is the data-tag for the CTFT."
-
- CTFTransform::usage =
- "CTFTransform[f, t] or CTFTransform[f, t, w] computes the \
- continuous-time Fourier transform of f. \
- It has time argument(s) t and frequency argument(s) w."
-
- InvCTFTransform::usage =
- "InvCTFTransform[f, w, t] computes the inverse continuous time \
- Fourier transform of f with frequency arguments w and time \
- arguments t."
-
- (* E N D U S A G E I N F O R M A T I O N *)
-
-
- Begin[ "`Private`" ]
-
-
- (* Messages *)
-
- Transform::laplace =
- "The Region of Convergence in the Laplace transform `` does not contain the imaginary axis so it cannot be converted into a Fourier transform."
-
-
- (* Options for the forward and inverse Fourier transforms *)
-
- displayFixUp[ op_ ] :=
- Append[ fixUp[op], TransformLookup -> Replace[TransformLookup, op] ]
-
- CTFTransform/: Options[ CTFTransform ] :=
- displayFixUp[ Join[ { Definition -> False, Dialogue -> False },
- Options[ InvLaPlace ] ] ]
-
- InvCTFTransform/: Options[ InvCTFTransform ] :=
- displayFixUp[ Join[ { Definition -> False,
- Dialogue -> False,
- Terms -> False},
- Options[ InvLaPlace ] ] ]
-
-
- (* Printed forms of local objects so that Dialogue -> All works neatly *)
-
- Format[ dualFT[ x_, w_, rest__, InvCTFTransform ] ] :=
- SequenceForm[ ColumnForm[{"F" Superscript[-1],
- " " ~StringJoin~ ToString[w]}],
- { x } ]
-
- Format[ dualFT[ x_, t_, rest__, CTFTransform ] ] :=
- SequenceForm[ ColumnForm[{"F",
- " " ~StringJoin~ ToString[t]}],
- { x } ]
-
- Format[ derivative[x_, w_Symbol, k_] ] :=
- SequenceForm[ ColumnForm[{"D" Superscript[k],
- " " ~StringJoin~ ToString[w]}],
- { x } ]
-
- Format[ integrate[x_, limits_] ] :=
- SequenceForm[ "Integrate[", x, ", ", limits, "]" ]
-
- Format[ substitute[x_, w_, wnew_] ] :=
- SequenceForm[ {x}, Subscript[w -> wnew] ]
-
- Format[ CTFTtoL[x_, w_, s_] ] :=
- SequenceForm[ {x}, Subscript[w -> s / I] ]
-
- Format[ SignalProcessing`Analog`Fourier`Private`s ] := "s"
-
-
- (* State definition for the unified rule base *)
-
- expandfield = 1 (* apply expand to the expression *)
- forlaplacefield = 2 (* all else has failed so try forward Laplace *)
- invlaplacefield = 3 (* all else has failed so try inverse Laplace *)
- definitionfield = 4 (* apply the Fourier transform definition *)
-
- statevariables = 4
-
- (* Global variables *)
- origVars = {}
- tranVars = {}
-
- (* Supporting routines *)
-
- explain[ dualFT[x_, t_, rest__, CTFTransform]] :=
- Message[ Transform::incomplete, "forward Fourier transform", x, t ]
- explain[ dualFT[x_, w_, rest__, InvCTFTransform]] :=
- Message[ Transform::incomplete, "inverse Fourier transform", x, w ]
-
- fixUp[ op_ ] := { Apart -> Replace[Apart, op],
- Definition -> Replace[Definition, op],
- Dialogue -> Replace[Dialogue, op],
- Simplify -> Replace[Simplify, op],
- Terms -> Replace[Terms, op] }
-
- initstate[] := Table[True, {statevariables}]
- initstate[ CTFTransform ] :=
- SetStateField[ initstate[], invlaplacefield, False ]
- initstate[ InvCTFTransform ] :=
- SetStateField[ initstate[], forlaplacefield, False ]
-
- LtoCTFT[ SignalProcessing`Analog`LaPlace`Private`mylaplace[x_, lrest__], t_, w_, s_, rest__ ] :=
- CTFTtoL[ dualFT[x, t, w, s, rest], w, s ]
- LtoCTFT[ x_, t_, w_, s_, trest__ ] := x
-
- mustbenegative[x_] := ! TrueQ[ Positive[x] ]
- mustbepositive[x_] := ! TrueQ[ Negative[x] ]
-
- posttransform[x_] := ( x /. postrules )
- postrules = {
- derivative[x_, t_, 1] :>
- D[ posttransform[x], t ],
- derivative[x_, t_, k_Integer] :>
- D[ posttransform[x], {t, k} ],
- integrate[x_, limits_] :>
- Integrate[ Expand[posttransform[x]], limits ],
- substitute[x_, -v_, v_] :>
- ( posttransform[x] /. v -> -v ),
- substitute[x_, t_, tnew_] :>
- ( posttransform[x] /. t -> tnew ),
- CTFTtoL[x_] :>
- Transform[ x, -Infinity, Infinity ],
- CTFTtoL[x_, w_, s_] :>
- Transform[ substitute[x, w, s / I], -Infinity, Infinity ],
- (a_ + b_. Sign[x_]) :> 2 a CStep[-x] /; ( a == -b ),
- (a_ + a_. Sign[x_]) :> 2 a CStep[x]
- }
-
- ROCincludesImagAxis[ trans_, op_ ] :=
- Block [ {cond, rm, rp, zerocond},
- rm = GetRMinus[trans];
- rp = GetRPlus[trans];
- cond = ( Negative[rm] && Positive[rp] );
- zerocond = ( ZeroQ[rm] || ZeroQ[rp] );
- If [ zerocond && SameQ[ Replace[Dialogue, op], All ],
- Print[ "assuming that the origin which is an endpoint" ];
- Print[ "of the region of convergence (ROC) of the" ];
- Print[ "Laplace transform is included in the ROC" ] ];
- If [ cond || zerocond,
- True,
- False,
- Assuming[cond, op]; True ] ]
-
- transform[dualFT[x_, rest__]] := Replace[dualFT[x, rest], DualFTRules]
- transform[x_] := x
-
- validvarQ[ x_Symbol ] := True
- validvarQ[ x_List ] := Apply[And, Map[VariableQ, x]]
- validvarQ[ x_ ] := False
-
-
- (* Extension of Fourier transform operators *)
-
- Unprotect[FT, InvFT]
- FT/: TheFunction[ FT[t_, w_] [f_] ] := CTFTransform[f, t, w]
- InvFT/: TheFunction[ InvFT[w_, t_] [f_] ] := InvCTFTransform[f, w, t]
- Protect[FT, InvFT]
-
-
- (* Extension of TheFunction operator *)
-
- CTFTData/: TheFunction[ CTFTData[x_, var_] ] := x
-
-
- (* Magnitude/Phase plot of a CTFT object *)
-
- mppoptions = { Domain -> Continuous, DomainScale -> Linear,
- MagRangeScale -> Log, PhaseRangeScale -> Degree,
- PlotRange -> All }
-
- CTFTData/: MagPhasePlot[ CTFTData[trans_, vars_], rest___ ] :=
- Apply [ MagPhasePlot, { trans, rest } ~Join~ mppoptions ]
-
-
- (* One-dimensional Fourier transform driver *)
-
- DualFT1d[ f_, t_, w_, s_, tlist_, wlist_, oplist_, dir_ ] :=
- Block [ {different, newexpr, newrules, oldexpr, simops, state, trace},
-
- Off[ Power::infy ];
- trace = SameQ[ Replace[Dialogue, oplist], All ];
- state = initstate[dir];
-
- (* Generate the 1-D FT rules *)
- newrules = TransformFixUp[ t, w, oplist, dualFT, False,
- dir, Null, Null ];
- If [ SameQ[dir, InvCTFTransform],
- newrules = newrules /. w -> -w ];
- DualFTRules = Join[ newrules, OriginalDualFTRules ];
-
- (* Embed the function in the dual ctft object *)
- If [ trace && SameQ[dir, InvCTFTransform],
- Print[ "The Duality Theorem will be used to" ];
- Print[ "find the inverse Fourier transform:" ] ];
- oldexpr = dualFT[f, t, w, s, fixUp[oplist], state, dir];
- If [ SameQ[dir, InvCTFTransform],
- oldexpr = dualFT[ f, t, w, s, fixUp[oplist],
- state, CTFTransform ];
- oldexpr = substitute[ oldexpr, w, -w ] / (2 Pi);
- If [ trace, Print[oldexpr]; Print["which becomes"] ] ];
-
- (* Simplify the function before transformation *)
-
- simops = { Dialogue -> trace, Variables -> tlist };
- If [ TrueQ[ $VersionNumber >= 2.0 ],
- PrependTo[simops, Trig -> False] ];
- newexpr = SPSimplify[ oldexpr, simops ];
-
- (* Transform the function *)
- different = True;
- If [ trace, Print[newexpr]; Print["which becomes"] ];
- While [ different,
- oldexpr = newexpr;
- newexpr = oldexpr /. ( dualFT[a__] :>
- Replace[dualFT[a], DualFTRules] );
- different = ! SameQ[newexpr, oldexpr];
- If [ different && trace,
- Print[newexpr]; Print["which becomes"] ] ];
-
- (* Fix up the transform *)
- different = True;
- While [ different,
- oldexpr = newexpr;
- newexpr = posttransform[oldexpr];
- different = ! SameQ[newexpr, oldexpr];
- If [ different && trace,
- Print[newexpr]; Print["which becomes"] ] ];
-
- (* Check for invalid Laplace transform substitutions *)
- newexpr /. LTransData[x_, rest__] :>
- Message[ Transform::laplace, x ];
-
- (* Simplify the resulting transform *)
- If [ trace, Print[newexpr] ];
- newexpr = SPSimplify[ newexpr,
- Variables -> wlist,
- Dialogue -> trace ];
-
- On[ Power::infy ];
-
- newexpr ]
-
-
-
-
- (* B E G I N F O R W A R D F O U R I E R T R A N S F O R M *)
-
-
- (* CTFTransform *)
- CTFTransform[ f_ ] :=
- Message[ Transform::novariables, "t (time)", GetVariables[f] ]
- CTFTransform[ f_, t_ ] :=
- CTFTransform[ f, t, DummyVariables[Length[t], Global`w] ]
- CTFTransform[ f_, t_, w_, options___ ] :=
- Message[ Transform::badvar, "time", CTFTransform, t ] /;
- ! validvarQ[t]
- CTFTransform[ f_, t_, w_, options___ ] :=
- Message[ Transform::badvar, "frequency", CTFTransform, w ] /;
- ! validvarQ[w]
- CTFTransform[ f_, t_, w_, options___ ] :=
- Block[ {op, svars, trans, vars},
- vars = Which [ Length[t] > Length[w],
- DummyVariables[Length[t], Global`w],
- Length[t] < Length[w],
- Take[w, Length[t]],
- True,
- w ];
- svars = DummyVariables[Length[t], s];
-
- origVars = t;
- tranVars = vars;
- op = ToList[options] ~Join~ Options[CTFTransform];
- trans = If [ Length[t] > 1,
- MultiDCTFT[f, t, vars, svars, op],
- MyFourier[f, t, vars, svars, op] ];
-
- If [ InformUserQ[op],
- Scan[explain, trans, Infinity] ];
-
- CTFTData[ FourierSimplify[trans], FVariables[vars] ] ]
-
- (* Multidimensional continuous-time Fourier transform *)
- MultiDCTFT[f1_, t_, w_, s_, op_] :=
- Block [ {i, func = f1, length},
- length = Length[t];
- For [ i = 1, i <= length, i++,
- func = MyFourier[ func, t[[i]], w[[i]],
- s[[i]], t, w, op ] ];
- func ]
-
- (* One-dimensional continuous-time Fourier transform *)
- MyFourier[ f_, t_, w_, s_, oplist_ ] :=
- DualFT1d[ f, t, w, s, {t}, {w}, oplist, CTFTransform ]
-
- MyFourier[ f_, t_, w_, s_, tlist_, wlist_, oplist_ ] :=
- DualFT1d[ f, t, w, s, tlist, wlist, oplist, CTFTransform ]
-
-
- (* E N D F O R W A R D F O U R I E R T R A N S F O R M *)
-
-
-
-
- (* B E G I N I N V E R S E F O U R I E R T R A N S F O R M *)
-
-
- (* InvCTFTransform *)
- InvCTFTransform[ CTFTData[x_, FVariables[w_]] ] := InvCTFTransform[x, w]
-
- InvCTFTransform[ CTFTData[x_, FVariables[w_]], rest__ ] :=
- InvCTFTransform[x, rest]
-
- InvCTFTransform[ x_, w_ ] :=
- InvCTFTransform[ x, w, DummyVariables[Length[w], Global`t] ]
-
- InvCTFTransform[ f_, w_, t_, options___ ] :=
- Message[ Transform::badvar, "frequency", InvCTFTransform, w ] /;
- ! validvarQ[w]
-
- InvCTFTransform[ f_, w_, t_, options___ ] :=
- Message[ Transform::badvar, "time", InvCTFTransform, t ] /;
- ! validvarQ[t]
-
- InvCTFTransform[ f_, w_, t_, options___ ] :=
- Block[ {op, s, svars, trans, vars},
- op = ToList[options] ~Join~ Options[InvCTFTransform];
-
- vars = Which [ Length[w] > Length[t],
- DummyVariables[Length[w], Global`t],
- Length[w] < Length[t],
- Take[t, Length[w]],
- True,
- t ];
-
- svars = DummyVariables[Length[w], s];
- origVars = w;
- tranVars = vars;
- trans = If [ Length[w] > 1,
- MultiDInvCTFT[f, w, vars, svars, op],
- MyInverseCTFT[f, w, vars, svars, op] ];
-
- If [ InformUserQ[op],
- Scan[explain, trans, Infinity] ];
-
- FourierSimplify[trans] ]
-
- (* MultiDInvCTFT *)
- MultiDInvCTFT[ f1_, w_, t_, s_, op_ ]:=
- Block [ {i, func = f1, length},
- length = Length[t];
- For [ i = 1, i <= length, i++,
- func = MyInverseCTFT[ func, w[[i]], t[[i]],
- s[[i]], w, t, op ] ];
- func ]
-
- (* driver for 1-D inverse CTFT rules *)
- MyInverseCTFT[ f_, w_, t_, s_, op_ ] :=
- DualFT1d[ f, w, t, s, {w}, {t}, op, InvCTFTransform ]
-
- MyInverseCTFT[ f_, w_, t_, s_, wlist_, tlist_, op_ ] :=
- DualFT1d[ f, w, t, s, wlist, tlist, op, InvCTFTransform ]
-
-
-
-
-
- (* E N D I N V E R S E F O U R I E R T R A N S F O R M *)
-
-
-
-
- (* B E G I N D U A L R U L E B A S E *)
-
- DualFTRules = {}
-
- OriginalDualFTRules = {
-
- (* Clean up any calls to the Laplace transform rule bases *)
- (* Must go before any other rules to avoid spurious Delta functions *)
-
- dualFT[ LTransData[x_, rest__], t_, w_, s_, op_, __ ] :>
- If [ ROCincludesImagAxis[ LTransData[x, rest], op ],
- x /. s -> I w,
- LTransData[x, rest] ] ,
-
- dualFT[ SignalProcessing`Analog`InvLaPlace`Private`myinvlaplace[x_,
- s_, restL__], t_, w_, s_, rest__ ] :>
- dualFT[ x /. s -> I t, t, w, s, rest ],
-
-
- (* A. Transform pairs *)
- (* 1. constant functions *)
- dualFT[ 0, t_, w_, __ ] :> 0,
- dualFT[ c_, t_, w_, __ ] :> 2 Pi c Delta[w] /; FreeQ[c, t],
-
- (* 2. two delta functions *)
- (* c delta(t + a) + d delta(t + b) where c = -d and a = -b *)
- (* c delta(t - b) - c delta(t + b) <---> -2 I c sin(b w) *)
- dualFT[ c_. Delta[t_ + a_] + d_. Delta[t_ + b_], t_, w_, __ ] :>
- -2 I c Sin[b w] /;
- ( a == -b ) && ( c == 1 || c == -1 ) && ( c == -d ) && FreeQ[{a, c}, t],
-
- (* c delta(t + a) + c delta(t + b) where c = -d and a = -b *)
- (* c delta(t - b) + c delta(t + b) <---> 2 c cos(b w) *)
- dualFT[ c_. Delta[t_ + a_] + c_. Delta[t_ + b_], t_, w_, __ ] :>
- 2 c Cos[b w] /;
- ( a == -b ) && FreeQ[{a, c}, t],
-
- (* 3. one delta function *)
- dualFT[ c_. Delta[t_ + t0_.], t_, w_, __ ] :>
- c Exp[I t0 w] /;
- FreeQ[{c, t0}, t],
-
- (* 4. impulse train *)
- dualFT[ x_. Periodic[T_, t_][y_. Delta[t_ + a_.]], t_, w_, rest__ ] :>
- (1 / Abs[T]) Exp[I a w] *
- Periodic[2 Pi / T, w][ dualFT[x y, t, w, rest] ] /;
- FreeQ[{a, n, y, T}, t],
-
- dualFT[ x_. Summation[n_Symbol, -Infinity, Infinity, 1][
- y_. Delta[t_ + a_. + n_ T_.]],
- t_, w_, rest__ ] :>
- (1 / Abs[T]) Exp[I a w] *
- Summation[n, -Infinity, Infinity, 1][
- substitute[ dualFT[x y, t, w, rest], w, w + 2 Pi n / T ] ] /;
- FreeQ[{a, n, T}, t] && FreeQ[y, n],
-
- (* 5. pulse functions *)
- dualFT[ CStep[t_ + a_] - CStep[t_ + b_] + x_., t_, w_, rest__ ] :>
- 2 a Sinc[a w] + dualFT[x, t, w, rest] /;
- FreeQ[a, t] && (a == -b),
-
- dualFT[ x_. + c_. ( CStep[t_ + a_.] - CStep[t_ + b_.] ), t_, w_, rest__ ] :>
- dualFT[c CPulse[Abs[b - a], t - Min[-a, -b]], t, w, rest] +
- dualFT[x, t, w, rest] /;
- FreeQ[{a, b}, t],
-
- dualFT[ CPulse[T_, t_ + a_.], t_, w_, __ ] :>
- T Exp[-I w T / 2] Exp[I a w] Sinc[w T / 2] /;
- FreeQ[{a, T}, t],
-
- (* 6. two-sided Gaussian *)
- dualFT[ Exp[a_. t_^2], t_, w_, s_, op_, rest___ ] :>
- Block [ {},
- Assuming[ Negative[a], op ];
- Sqrt[Pi] Exp[w^2 / (4 a)] / Sqrt[-a] ] /;
- FreeQ[a, t] && mustbenegative[a],
-
- (* 7. cosine x over x in time *)
- dualFT[ Cos[a_. t_] / t_, t_, w_, __ ] :>
- Abs[a] I ( CStep[-Abs[a] - w] - CStep[w - Abs[a]] ) /;
- FreeQ[a, t],
-
- (* 8. two-sided cosine *)
- dualFT[ Cos[w0_. t_ + b_.], t_, w_, __ ] :>
- Exp[I w b / w0] Pi ( Delta[w - w0] + Delta[w + w0] ) /;
- FreeQ[{b, w0}, t],
-
- (* 9. two-sided sine *)
- dualFT[ Sin[w0_. t_ + b_.], t_, w_, __ ] :>
- Exp[I w b / w0] Pi / I ( Delta[w - w0] - Delta[w + w0] ) /;
- FreeQ[{b, w0}, t],
-
- (* 10. two-sided sinc *)
- dualFT[ Sin[a_. t_] / t_, t_, w_, __ ] :>
- Pi CPulse[2 a, w + a] /;
- FreeQ[a, t],
-
- dualFT[ Sinc[a_. t_ + b_.], t_, w_, __ ] :>
- Exp[I w b / a] Pi CPulse[2 a, w + a] / a /;
- FreeQ[{a,b}, t], (* CPulse[2a, w+a] = CStep[w+a] - CStep[w-a] *)
-
- dualFT[ (Sinc[a_. t_ + b_.])^2, t_, w_, __ ] :>
- Exp[I w b / a] (Pi / a)^2 *
- ( Unit[-2][w + 2 a] - 2 Unit[-2][w] + Unit[-2][w - 2 a] ) /;
- FreeQ[{a,b}, t],
-
- (* 11. other two-sided forms *)
- dualFT[ Exp[-Abs[a_. t_]] Sinc[a_. t_], t_, w_, __ ] :>
- ArcTan[ 2 a^2 / w^2 ] / a /;
- FreeQ[a, t],
-
- dualFT[ Sign[t_ + t0_.], t_, w_, __ ] :>
- 2 I Exp[I t0 w] / w /;
- FreeQ[t0, w],
-
- dualFT[ 1 / t_, t_, w_, __ ] :> I Pi Sign[w],
-
- dualFT[ BesselJ[0, a_. t_], t_, w_, __ ] :>
- CPulse[2 a, w + a] / ( Pi Sqrt[a^2 - w^2] ) /;
- FreeQ[a, t],
-
- dualFT[ CStep[t_ + t0_.], t_, w_, __ ] :>
- I Exp[I t0 w] / w + Pi Delta[w] /;
- FreeQ[t0, t], (* because Pi Exp[I t0 w] Delta[w] <--> Pi Delta[w] *)
-
- dualFT[ CStep[-t_ + t0_.], t_, w_, __ ] :>
- -I Exp[-I t0 w] / w + Pi Delta[w] /;
- FreeQ[t0, t],
-
- (* B. Properties *)
- (* 1. homogeneity *)
- dualFT[ a_ x_, t_, w_, rest__ ] :>
- a dualFT[ x, t, w, rest ] /; FreeQ[a, t],
-
- (* 2. additivity *)
- dualFT[ a_ + b_, t_, w_, rest__ ] :>
- dualFT[ a, t, w, rest ] + dualFT[ b, t, w, rest ],
-
- dualFT[ Summation[i_, il_, iu_, inc_][f_], t_, w_, rest___ ] :>
- Summation[i, il, iu, inc][ dualFT[f, t, w, rest] ] /;
- FreeQ[{i, il, iu, inc}, t],
-
- (* 3. one-sided transform *)
- dualFT[ x_. CStep[t_ + t0_], t_, w_, rest__ ] :>
- Exp[- I w t0] dualFT[ ( x /. t -> (t - t0)) CStep[t], t, w, rest ] /;
- FreeQ[t0, t],
-
- (* 4. derivative *)
- dualFT[ Derivative[k_][x_][t_], t_, w_, rest__ ] :>
- (I w)^k dualFT[ x[t], t, w, rest ] /;
- FreeQ[k, t],
-
- (* 5. integration *)
- dualFT[ Integrate[x_, {tau_, -Infinity, t_}], t_, w_, rest__ ] :>
- Block [ {trans},
- trans = dualFT[x, tau, w, rest];
- trans ( 1/(I w) + Pi Delta[w] ) ],
-
- (* 6. multiply by time *)
- dualFT[ t_^a_. x_, t_, w_, s_, op_, rest___ ] :>
- Block [ {dialogue},
- dialogue = SameQ[ Replace[Dialogue, op], All ];
- Assuming[ Positive[a], dialogue ];
- If [ dialogue, Print[ "where ", a, " is an integer" ] ];
- I^a derivative[ dualFT[x, t, w, s, op, rest], w, a ] ] /;
- FreeQ[a, t] && Implies[ NumberQ[a], IntegerQ[a] && a > 0 ],
-
- (* 7. divide by time *)
- dualFT[ x_ / t_^k_., t_, w_, rest__ ] :>
- -I integrate[ dualFT[x / t^(k-1), t, w, rest], {w, -Infinity, w} ] +
- I Pi Limit[x, t -> 0] /;
- N[ k >= 1 ] && ! InfinityQ[ Limit[x, t -> 0] ],
-
- (* 8. exponential raised to an imaginary power times a function *)
- dualFT[ x_. Exp[ Complex[0, w0_] w1_. t_ + restexp_. ], t_, w_, rest__ ] :>
- substitute[ dualFT[x Exp[restexp], t, w, rest], w, w - w0 w1 ] /;
- FreeQ[{w0, w1}, t],
-
- (* 9. convolution *)
- dualFT[ CConvolve[t_][x_, restconv__], t_, w_, rest__ ] :>
- Apply[ Times, Map[ dualFT[#1, t, w, rest]&, { x, restconv } ] ],
-
-
- (* C. Strategies *)
- (* 1. expand expression *)
- dualFT[ x_, t_, w_, s_, oplist_, state_, rest___ ] :>
- dualFT [ Expand[x], t, w, s, oplist,
- SetStateField[state, expandfield, False], rest ] /;
- GetStateField[state, expandfield],
-
- (* 2. function times a window *)
- dualFT[ x_ CPulse[l_, t_ + a_.], t_, w_, __ ] :>
- Integrate[ x Exp[- I w t], {t, -a, -a + l} ] /;
- FreeQ[{a, l}, t],
-
- (* 3. Apply the definition if Definition options is enabled *)
- dualFT[ x_, t_, w_, s_, op_, state_, dir_ ] :>
- Block [ {newstate, trans},
- newstate = SetStateField[state, definitionfield, False];
- trans = Integrate[x Exp[- I w t],
- {t, -Infinity, Infinity}];
- If [ SameQ[Head[trans], Integrate],
- dualFT[x, t, w, s, op, newstate, dir],
- TransformDialogue[ Definition, op, Integrate,
- x, trans ] ] ] /;
- GetStateField[state, definitionfield] && Replace[Definition, op],
-
- (* 4. Try a forward or inverse Laplace transform if all else fails *)
- dualFT[ x_, t_, w_, s_, oplist_, state_, dir_ ] :>
- Block [ {ltrans, newstate},
- ltrans = LaPlace[ x, t, s,
- { Dialogue -> False } ~Join~ oplist ];
- If [ InformUserQ[oplist],
- Print[ "( after taking the Laplace transform of " ];
- Print[ " ", x ];
- Print[ " with respect to ", t, " and" ];
- Print[ " adjusting the result )" ] ];
- newstate = SetStateField[state, forlaplacefield, False];
- If [ SameQ[Head[ltrans], LTransData],
- If [ ROCincludesImagAxis[ ltrans, op ],
- ( TheFunction[ltrans] /. s -> I w ),
- dualFT[ x, t, w, s, oplist, newstate, dir ] ],
- MapAll[ LtoCTFT[#1, t, w, s, oplist, newstate, dir]&,
- ltrans ] ] ] /;
- GetStateField[state, forlaplacefield],
-
- dualFT[ x_, w_, t_, s_, op_, state_, dir_ ] :>
- Block [ {invltrans, newstate, newx},
- newx = (x /. w -> (s / I));
- invltrans = InvLaPlace[ 2 Pi newx, s, t,
- { Dialogue -> False } ~Join~ op ];
- If [ InformUserQ[op],
- Print[ "( after taking the inverse Laplace transform of" ];
- Print[ " ", newx /. s -> "s" ];
- Print[ " which yields" ];
- Print[ " ", invltrans ];
- Print[ " and adjusting the result )" ] ];
- newstate = SetStateField[state, invlaplacefield, False];
- If [ FreeQ[invltrans, s],
- substitute[invltrans, t, -t], (* FT uses L^-1 so t=-t *)
- dualFT[ x, w, t, s, op, newstate, dir ] ] ] /;
- GetStateField[state, invlaplacefield]
-
- }
-
-
- (* E N D P A C K A G E *)
-
- End[]
- EndPackage[]
-
- If [ TrueQ[ $VersionNumber >= 2.0 ],
- On[ General::spell ];
- On[ General::spell1 ] ];
-
-
- (* H E L P I N F O R M A T I O N *)
-
- Combine[ SPfunctions, { CTFTransform, InvCTFTransform } ]
- Protect[ CTFTransform, InvCTFTransform ]
-
-
- (* E N D I N G M E S S A G E *)
-
- Print[ "The continuous Fourier transform (CTFT) functions are loaded." ]
- Null
-